<?php
require_once(SYSTEM_PATH . 'lib/Handler_directory.php');
/**
 * Log日志类
 * write函数为私有函数，所有需要写日志的地方都需要新加一个函数来显示调用write函数。
 * 代码虽然会有冗余，但易于对日志逻辑的管理。
 */
class Log_File {

    //PHP系统内置错误代码及定义
    protected static $errorCodes = array(
                                    1       => "E_ERROR: Fatal run-time errors.",
                                    2       => "E_WARNING: Run-time warnings(non-fatal errors).",
                                    4       => "E_PARSE: Compile-time parse errors.",
                                    8       => "E_NOTICE: Run-time notices. Indicate something that could have an error.",
                                    16      => "E_CORE_ERROR: Fatal errors that occur during PHP's initial startup.",
                                    32      => "E_CORE_WARNING: Warnings(non-fatal errors) that occur during PHP's initial startup.",
                                    64      => "E_COMPILE_ERROR: Fatal compile-time errors(generated by Zend Scripting Engine).",
                                    128     => "E_COMPILE_WARNING: Compile-time warnings(non-fatal errors, generated by Zend Scripting Engine).",
                                    256     => "E_USER_ERROR: User-generated error message(generated by using trigger_error()).",
                                    512     => "E_USER_WARNING: User-generated warning message(generated by using trigger_error()).",
                                    1024    => "E_USER_NOTICE: User-generated notice message(generated by using trigger_error()).",
                                    2048    => "E_STRICT: PHP suggest changes to your code ensure the best interoperability and forward compatibility.",
                                    4096    => "E_RECOVERABLE_ERROR: Catchable fatal error.",
                                    8192    => "E_DEPRECATED: Run-time notices(code will not work in future versions).",
                                    16384   => "E_USER_DEPRECATED: User-generated warning message(generated by using trigger_error()).",
                                    30719   => "E_ALL: All errors and warnings, except of level E_STRICT in PHP < 6."
                                );

    /**
     * 根据错误代码获取对应的信息
     * @param <int> $codemask PHP预定义的错误代码
     * @return <string> 对应的错误信息
     */
    protected static function getErrorCode($codemask){
        if( empty($codemask) ){
            return "";
        }
        return self::$errorCodes[$codemask];
    }

    /**
     * 获取最后一次错误信息, 并对格式进行编排
     * @return <string> 最后一次错误信息
     */
    protected static function getLastErrorMessage(){
        $error = error_get_last();
        if( empty($error) ){
            return "";
        }
        //var_dump($error);exit;
        $lastErrorMsg = "last error: [type]=(" . $error["type"] . ")" . self::getErrorCode( $error["type"] ) . "\r\n";
        $lastErrorMsg .= "\t[message]=" . $error["message"] . "\r\n";
        $lastErrorMsg .= "\t[file]=" . $error["file"] . " (" . $error["line"] . ")\r\n";
        return $lastErrorMsg;
    }

    /**
     * 初始化错误日志的信息和格式
     */
    private static function getFormat($msg){
        $txt = "\r\n" . "time: " . date("Y-m-d H:i:s") . "\r\n";
        if( !empty($_SERVER) ){
            $txt .= "server ip: " . $_SERVER['SERVER_ADDR'] . "\r\n";
            $txt .= "browser: " . Handler_http::getBrowserInfo(true) . "\r\n";
            $txt .= "project name: " .APP_NAME . "\r\n";
            $txt .= "http url : " .$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"] . "\r\n";
        }
        $txt .= empty($msg) ? "" : $msg . "\r\n";
        return $txt;
    }

    /**
     * 将日志写入文件，所有写日志的函数最终都会调用此私有函数
     * @param <string> $type 日志的类型，主要用于对日志进行分类，比如数据库日志放入db目录下，$type的值就是db
     * @param <string> $msg 日志信息
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    private static function write($type, $msg, $appendLastError = false){
        if( empty($type) ){
            return false;
        }

        //把日志按类型分目录存放，且以xxxx_xx格式的目录分期存放，日志以天为单位，命名格式是xxxx_xx_xx
        //$path = LOG_PATH . DIRECTORY_SEPARATOR . trim($type) . DIRECTORY_SEPARATOR . date("Y_m") . DIRECTORY_SEPARATOR;
        //$file = date("Y_m_d") . ".txt";
        $path = LOG_PATH . DIRECTORY_SEPARATOR . date("Y_m") . DIRECTORY_SEPARATOR . date("d") . DIRECTORY_SEPARATOR;
        $file = trim($type) . ".txt";
        $filepath = $path . $file;
        //创建目录
        $isCreated = Handler_directory::CreateServerFolder($path);

        //写文件，如果文件不存在则创建新文件
        $mode = "a+";
        if( !file_exists($filepath) ){
            $mode = "w+";
        }
        if ( ! $fp = @fopen($filepath, $mode) ){
            return false;
        }

        //日志内容
        $msg = self::getFormat($msg);
        //追加最后一次错误信息
        if($appendLastError){
            $msg .= self::getLastErrorMessage();
        }
        //加锁写入数据到文件尾部
        flock($fp, LOCK_EX);
        fwrite($fp, $msg);
        //解锁关闭文件
        flock($fp, LOCK_UN);
        fclose($fp);
        //将文件的权限设为可写
        @chmod($filepath, 0755);
        @chown($filepath, 'etpass-fpm');
        @chgrp($filepath, 'etpass-fpm');
        return true;
    }

    /**
     * 将日志以CSV格式写入文件，用于记录各类数据，而非错误信息
     * 所有写CSV日志的函数最终都会调用此私有函数
     * @param <string> $type 日志的类型，主要用于对日志进行分类，比如数据库日志放入db目录下，$type的值就是db
     * @param <string> $msg 日志信息
     * @return <type> 写入成功返回true，否则返回false
     */
    private static function write_csv($type, $msg){
        return self::write('csv_' . $type, $msg, false);
    }

    /**
     * 用于记录DB错误信息，置于Log目录下的db文件
     * @param <string> $msg 要写入日志的信息
     * @param <bool> $appendLastError 是否追加最后一次错误的信息，默认为false
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeDBLog($msg, $appendLastError = true){
        if( empty($msg) || trim($msg) == "" ){
            return FALSE;
        }
        $msg = "file: " . $_SERVER ['SCRIPT_NAME'] . "\r\n" . $msg;
        return self::write( "db", trim($msg), $appendLastError );
    }

    /**
     * 用于记录用户自定义的错误信息，置于Log目录下的sys_error文件
     * @param <string> $msg 要写入日志的信息
     * @param <bool> $appendLastError 是否追加最后一次错误的信息，默认为false
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeSysErrorLog($errno, $msg, $errorfile, $errline, $appendLastError = true){
        if( empty($msg) || trim($msg) == "" ){
            return FALSE;
        }
        $msg = "file: " . $errorfile . ' on line ' . $errline ."\r\n" . self::$errorCodes[$errno] . "\r\n" . $msg;
        return self::write( "sys_error", trim($msg), $appendLastError );
    }

    /**
     * 用于记录异常中的错误信息，置于Log目录下的sys_error文件
     * @param <string> $msg 要写入日志的信息
     * @param <bool> $appendLastError 是否追加最后一次错误的信息，默认为false
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeExecptionLog($msg, $appendLastError = true){
        if( empty($msg) || trim($msg) == "" ){
            return FALSE;
        }
        $msg = "error: " . trim($msg);
        return self::write( "sys_error", $msg, $appendLastError );
    }
    
    /**
     * 用于记录指定接口异常的错误信息，置于Log目录下的指定的文件中
     * @param <string> $msg 要写入日志的信息
     * @param <bool> $appendLastError 是否追加最后一次错误的信息，默认为false
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeOtherInterfaceLog($msg,$log_file_name, $appendLastError = true){
        if( empty($msg) || trim($msg) == "" ){
            return FALSE;
        }
        $msg = trim($msg);
        return self::write( $log_file_name, $msg, $appendLastError );
    }

    /**
     * 用于记录发送邮件时发生的错误，置于Log目录下的mail文件
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeMailErrorLog($msg){
        if( empty($msg) || trim($msg) == "" ){
            return FALSE;
        }
        $msg = "error: " . trim($msg);
        return self::write( "mail", $msg, true );
    }

    /**
     * 写短信发送错误日志，置于Log目录下的sms文件
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeSMSErrorLog($msg){
        if( empty($msg) || trim($msg) == "" ){
            return FALSE;
        }
        $msg = empty($msg) ? "" : "error: " . $msg;
        return self::write( "sms", trim($msg), false );
    }

    /**
     * 写机票日志，示例，勿直接调用，可按需求自行添加
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeFlightLog($dir_name, $msg){
        if( empty($dir_name) || empty($msg) || trim($msg) == "" ){
            return false;
        }
        return self::write( $dir_name, trim($msg), false );
    }

    /**
     * 写酒店错误日志，示例，勿直接调用，可按需求自行添加
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeHotelLog($dir_name, $msg){
        if( empty($dir_name) || empty($msg) || trim($msg) == "" ){
            return false;
        }
        return self::write( $dir_name, trim($msg), false );
    }
    
    /**
     * 记录接口访问时间日志
     *
     * @param string $method 接口名
     * @param string $msg 日志消息
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeRpc($method, $msg)
    {
        if(empty($method) || empty($msg) ){
            return false;
        }
        return self::write( 'rpc_' . $method, trim($msg), false );
    }
    
    /**
     * 调用支付接口日志
     *
     * @param string $method 接口名
     * @param string $msg 日志消息
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeOrderpay($msg)
    {
        if(empty($msg) || "" == trim($msg) ){
            return false;
        }
        return self::write( 'Flight_OrderPay', trim($msg), false );
    }
    
    /**
     * 记录向CPS联盟网站发送的请求
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeCPSLog($msg){
    	 if(empty($msg) || trim($msg) == "" ){
            return false;
        }
        return self::write( "cps", trim($msg), false );
    }
    
    /**
     * 记录向CPS联盟网站发送请求出错时的日志
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeCPSErrorLog($msg){
    	if(empty($msg) || trim($msg) == "" ){
    		return false;
    	}
    	return self::write( "cps_error", trim($msg), false );
    }

    /**
     * 记录酒店后台处理
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeHotelAdminLog($msg){
        if( empty($msg) || trim($msg) == "" ){
            return false;
        }
        return self::write( "hotel_admin", trim($msg), false );
    }

    /**
     * 记录Handler_http::sendSocketRequest函数的调用错误日志
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeSocketRequestLog($msg){
        if( empty($msg) || trim($msg) == "" ){
            return false;
        }
        return self::write( "SocketRequest", trim($msg), true );
    }
    
     /**
     * 记录数据添加日志
     *
     * @param string $msg 日志消息
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
	 public static function writeHotelSyncLog($msg){
		 if(empty($msg) || trim($msg) == "" ){
	        return false;
	    }
	    return self::write("app_hotel_sync_error",trim($msg), true );
	}
	
	/**
     * 记录数据添加日志
     *
     * @param string $msg 日志消息
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
	 public static function writeSyncLog($method,$msg){
		 if(empty($method) || empty($msg)){
	        return false;
	    }
	    return self::write('h_' . $method, trim($msg));
	}
    /**
     * 国际机票会员中心取消订单日志
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeFlightsIatLog($msg){
        if( empty($msg) || trim($msg) == "" ){
            return FALSE;
        }
        $msg = "error: " . trim($msg);
        return self::write( "flights_iat_ordercancel", $msg, true );
    }

    /**
     * 联盟跳转中转页日志
     * @param <string> $msg 日志内容
     * @param <bool> $appendLastError 是否追加最后一次系统错误
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeWelcomePortalLog($msg, $appendLastError = true){
        if( empty($msg) || trim($msg) == "" ){
            return FALSE;
        }
        return self::write( "welcome_portal", $msg, $appendLastError );
    }
    
	/**
     * 联合登录中转页日志
     * @param <string> $msg 日志内容
     * @param <bool> $appendLastError 是否追加最后一次系统错误
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeWelcomeUnionLoginLog($msg, $appendLastError = true){
        if( empty($msg) || trim($msg) == "" ){
            return FALSE;
        }
        return self::write( "welcome_UnionLogin", $msg, $appendLastError );
    }
    
	/**
     * QQ登录中转页日志
     * @param <string> $msg 日志内容
     * @param <bool> $appendLastError 是否追加最后一次系统错误
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeWelcomeQQLoginLog($msg, $appendLastError = true){
        if( empty($msg) || trim($msg) == "" ){
            return FALSE;
        }
        return self::write( "welcome_QQLogin", $msg, $appendLastError );
    }
    
	/**
     * 支付宝登录中转页日志
     * @param <string> $msg 日志内容
     * @param <bool> $appendLastError 是否追加最后一次系统错误
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeWelcomeAlipayLoginLog($msg, $appendLastError = true){
        if( empty($msg) || trim($msg) == "" ){
            return FALSE;
        }
        return self::write( "welcome_AlipayLogin", $msg, $appendLastError );
    }
	/**
     * 163登录中转页日志
     * @param <string> $msg 日志内容
     * @param <bool> $appendLastError 是否追加最后一次系统错误
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeWelcomeNeteaseLoginLog($msg, $appendLastError = true){
        if( empty($msg) || trim($msg) == "" ){
            return FALSE;
        }
        return self::write( "welcome_NeteaseLogin", $msg, $appendLastError );
    }
	
	/**
     * 139登录中转页日志
     * @param <string> $msg 日志内容
     * @param <bool> $appendLastError 是否追加最后一次系统错误
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeWelcomeCMCCLoginLog($msg, $appendLastError = true){
        if( empty($msg) || trim($msg) == "" ){
            return FALSE;
        }
        return self::write( "welcome_CMCCLogin", $msg, $appendLastError );
    }

    /*
     * 酒店部分日志
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeAppHotelErrorLog($msg){
        if(empty($msg) || trim($msg) == "" ){
            return false;
        }
        return self::write( "app_hotel_error", trim($msg), true );
    }
    
    /**
     * 记录会员错误日志
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeAppMemberErrorLog($msg){
        if(empty($msg) || trim($msg) == "" ){
            return false;
        }
        return self::write( "app_member_error", trim($msg), true );
    }
    /**
     * 记录机票Memchche日志
     * @param <string> $msg 日志内容
     * @param <bool> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeFlightMemcacheLog($msg){
        if(empty($msg) || trim($msg) == "" ){
            return false;
        }
        return self::write( "flight_memcache_error", trim($msg), true );
    }
   /**
     * 记录酒店后台(wwwadmin.etpass.com)操作日志
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
     public static function writeAppwwwadminLog($msg){
        if(empty($msg) || trim($msg) == "" ){
            return false;
        }
        return self::write( "app_wwwadmin_log", trim($msg), true );
    }
    /**
     * 记录机型配置不存在的日志
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writePlaneModelError($msg){
    	if(empty($msg) || trim($msg) == "" ){
    		return false;
    	}
    	return self::write( "plane_model", trim($msg), true );
    }
    /**
     * 记录机型配置不存在的日志
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeSpaceError($msg){
    	if(empty($msg) || trim($msg) == "" ){
    		return false;
    	}
    	return self::write( "Flight_Space_null", trim($msg), true );
    }
    
    /**
     * 记录serviceSearch类来源日志
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function writeServiceSearch($msg){
    	if(empty($msg) || trim($msg) == "" ){
    		return false;
    	}
    	return self::write( "serviceSearch", trim($msg), true );
    }
    
    /**
     * 记录移动端进入机票订单填写页时，找不到缓存
     * @param <string> $msg 日志内容
     * @return <bool> 是否写入成功，是返回true，否则返回false
     */
    public static function mobile_flight_cache_error($msg){
    	if(empty($msg) || trim($msg) == "" ){
    		return false;
    	}
    	return self::write( "Flight_Cache_Error", trim($msg), true );
    }
}
?>